use core::ptr::NonNull;

use crate::fcan::FCanRegs;

/// Number of FCAN controllers
pub const FCAN_CONTROLLERS: usize = 2;

// CAN Frame Flags
pub const CAN_EFF_FLAG: u32 = 0x80000000; // Extended frame format flag
pub const CAN_RTR_FLAG: u32 = 0x40000000; // Remote transmission request flag
pub const CAN_SFF_MASK: u32 = 0x000007FF; // Standard frame format mask
pub const CAN_EFF_MASK: u32 = 0x1FFFFFFF; // Extended frame format mask

// CAN FD Flags
pub const CANFD_BRS: u8 = 0x03; // Bit rate switching
pub const CANFD_ESI: u8 = 0x04; // Error state indicator

/// Maximum data length for CAN FD frames
pub const FCAN_DATA_LENGTH: usize = 64;

// Frame types
pub const STANDARD_FRAME: u32 = 0;
pub const EXTEND_FRAME: u32 = 1;

// FCAN Control Register Bit Masks
pub const FCAN_CTRL_XFER_MASK: u32 = 1 << 0; // Transfer enable
pub const FCAN_CTRL_TXREQ_MASK: u32 = 1 << 1; // Transmit request
pub const FCAN_CTRL_AIME_MASK: u32 = 1 << 2; // Acceptance identifier mask enable
pub const FCAN_CTRL_RST_MASK: u32 = 1 << 7; // Soft reset
pub const FCAN_CTRL_RFEIDF_MASK: u32 = 1 << 8; // Frame recv completion interrupt when filtering
pub const FCAN_CTRL_IRFEDT_MASK: u32 = 1 << 9; // Frame recv completion interrupt when sending
pub const FCAN_CTRL_IOF_MASK: u32 = 1 << 10; // Send overload frame
pub const FCAN_CTRL_FDCRC_MASK: u32 = 1 << 11; // Stuff count, CRC mode

// CANFD位掩码
pub const FTCANFD_ID1_FDL_MASK: u32 = 1 << 18; // CANFD Standard FDF
pub const FTCANFD_ID1_BRS_MASK: u32 = 1 << 16; // CANFD Standard BRS
pub const FTCANFD_ID1_ESI_MASK: u32 = 1 << 15; // CANFD Standard ESI
pub const FTCANFD_IDR_PAD_MASK: u32 = 0x000007FF; // CANFD Standard msg padding
pub const FTCANFD_ID2_FDL_MASK: u32 = 1 << 31; // CANFD Extended FDF
pub const FTCANFD_ID2_BRS_MASK: u32 = 1 << 29; // CANFD Extended BRS
pub const FTCANFD_ID2_ESI_MASK: u32 = 1 << 28; // CANFD Extended ESI
pub const FTCANFD_ID2_EDLC_MASK: u32 = 0x0000000F; // CANFD Extended DLC mask

// CAN帧ID相关位掩码和移位
pub const FCAN_IDR_ID1_SHIFT: u32 = 21; // Standard Message Identifier shift
pub const FCAN_IDR_SDLC_SHIFT: u32 = 14; // Standard DLC shift
pub const FCAN_IDR_EDLC_SHIFT: u32 = 26; // Standard Extended DLC shift
pub const FCANFD_IDR_EDLC_SHIFT: u32 = 24; // CANFD Extended DLC shift
pub const FCANFD_IDR1_SDLC_SHIFT: u32 = 11; // CANFD Standard DLC shift
pub const FCAN_IDR_SRR_MASK: u32 = 1 << 20; // Substitute remote TXreq
pub const FCAN_IDR_IDE_MASK: u32 = 1 << 19; // Identifier extension
pub const FCAN_IDR_RTR_MASK: u32 = 1 << 0; // Remote TX request
pub const FCAN_IDR_PAD_MASK: u32 = 0x00003FFF; // Standard msg padding

// FCAN Return Codes
pub const FCAN_SUCCESS: i32 = 0;
pub const FCAN_FAILURE: i32 = -1;
pub const FCAN_INVAL_PARAM: i32 = -2;

// FCAN IDs
pub const FCAN0_ID: u32 = 0;
pub const FCAN1_ID: u32 = 1;
pub const FCAN_NUM: u32 = 2;

// FIFO Related Constants
pub const CAN_FIFO_BYTE_LEN: u32 = 256; // CAN FIFO total byte length
pub const KEEP_CAN_FIFO_MIN_LEN: u32 = 64; // Minimum CAN FIFO length to keep
pub const KEEP_CANFD_FIFO_MIN_LEN: u32 = 68; // Minimum CAN FD FIFO length to keep

// FIFO Counter Bit Masks
pub const FCAN_FIFO_CNT_RFN_MASK: u32 = 0x7F; // Receive FIFO valid data number mask
pub const FCAN_FIFO_CNT_TFN_MASK: u32 = 0x7F; // Transmit FIFO valid data number mask

/// Extract receive FIFO count
pub const fn fcan_fifo_cnt_rfn_get(x: u32) -> u32 {
    x & 0x7F // GET_REG32_BITS((x), 6, 0)
}

/// Extract transmit FIFO count
pub const fn fcan_fifo_cnt_tfn_get(x: u32) -> u32 {
    (x >> 16) & 0x7F // GET_REG32_BITS((x), 22, 16)
}

/// CAN timing parameters constants, corresponding to C struct FCanBittimingConst
pub struct FCanBitimingConst {
    pub tseg1_min: u32, // Time segment 1 = prop_seg + phase_seg1
    pub tseg1_max: u32,
    pub tseg2_min: u32, // Time segment 2 = phase_seg2
    pub tseg2_max: u32,
    pub sjw_max: u32, // Synchronisation jump width
    pub brp_min: u32, // Bit-rate prescaler
    pub brp_max: u32,
    pub brp_inc: u32,
}

/// CAN frame structure
pub struct FCanFrame {
    pub id: u32,        // CAN identifier
    pub candlc: u8,     // CAN data length code
    pub flags: u8,      // CAN frame flags
    pub data: [u8; 64], // CAN frame data
}

impl FCanFrame {
    /// Create a new CAN frame with default values
    pub fn new() -> Self {
        Self {
            id: 0,
            candlc: 0,
            flags: 0,
            data: [0; 64],
        }
    }
}

/// CAN frame type
#[derive(Clone, Copy)]
pub enum FCanFrameType {
    Standard = 0,
    Extended = 1,
}

/// CAN ID mask configuration
#[derive(Clone, Copy)]
pub struct FCanIdMaskConfig {
    pub filter_index: u32,         // Filter index (0-3)
    pub id: u32,                   // CAN ID to filter
    pub mask: u32,                 // Mask for filtering
    pub frame_type: FCanFrameType, // Frame type (standard or extended)
}

#[repr(C)]
pub struct FCanRegisters(pub FCanRegs);

/// Arbitration segment timing defaults
pub const FCAN_ARB_BIT_CONST: FCanBitimingConst = FCanBitimingConst {
    tseg1_min: 1,
    tseg1_max: 16,
    tseg2_min: 1,
    tseg2_max: 8,
    sjw_max: 4,
    brp_min: 1,
    brp_max: 8192,
    brp_inc: 1,
};

/// Data segment timing defaults
pub const FCAN_DATA_BIT_CONST: FCanBitimingConst = FCanBitimingConst {
    tseg1_min: 1,
    tseg1_max: 16,
    tseg2_min: 1,
    tseg2_max: 8,
    sjw_max: 4,
    brp_min: 1,
    brp_max: 8192,
    brp_inc: 1,
};

/// FCAN segment type
#[derive(PartialEq, Clone, Copy)]
pub enum FCanSegmentType {
    Arbitration = 0,
    Data = 1,
}

/// FCAN baudrate configuration
#[derive(Clone, Copy)]
pub struct FCanBaudrateConfig {
    pub segment: FCanSegmentType, // Segment type (arbitration or data)
    pub auto_calc: bool,          // Whether to automatically calculate timing parameters
    pub baudrate: u32,            // Target baudrate
    pub sample_point: u32,        // Sample point in 0.1% (per mill)
    pub prop_seg: u32,            // Propagation segment
    pub phase_seg1: u32,          // Phase segment 1
    pub phase_seg2: u32,          // Phase segment 2
    pub sjw: u32,                 // Synchronization jump width
    pub brp: u32,                 // Bit rate prescaler
}

impl FCanBaudrateConfig {
    /// Create a new baudrate configuration with automatic calculation enabled
    pub fn new(segment: FCanSegmentType, baudrate: u32) -> Self {
        Self {
            segment,
            auto_calc: true,
            baudrate,
            sample_point: 0,
            prop_seg: 0,
            phase_seg1: 0,
            phase_seg2: 0,
            sjw: 0,
            brp: 0,
        }
    }
}

/// FCAN controller
pub struct FCanController {
    pub base: NonNull<FCanRegisters>, // Base address
    pub is_ready: bool,               // Initialization status
    pub use_canfd: bool,              // Whether CAN FD is enabled
    pub caps: u32,                    // Controller capabilities
}

/// FCAN system containing all controllers
pub struct FCanSystem {
    pub controllers: [FCanController; FCAN_CONTROLLERS],
}
